﻿using System;
using System.Drawing;
using System.Windows.Forms;
using Map_Creator.MapInfo;
using Map_Creator.Painters;
using Map_Creator.XNA;
using Microsoft.Xna.Framework.Graphics;
using XnaColor = Microsoft.Xna.Framework.Color;
using XnaPoint = Microsoft.Xna.Framework.Point;
using XnaRectangle = Microsoft.Xna.Framework.Rectangle;

namespace Map_Creator.MainForm.Controls
{
    public partial class TilesPanel : GraphicsDeviceControl
    {
        public DataPainter DataPainter;

        public bool IsDrawGrid = true;

        public TilesPanel()
        {
            InitializeComponent();

            TileSet.PrimaryTileSetChanged += TileSet_PrimaryTileSetChanged;
            TileSet.SelectedDataGridChanged += TileSet_SelectedDataGridChanged;
        }

        protected override void Draw(PaintEventArgs e)
        {
            if (MapInfo.Map.SelectedMap == null) return;
            if (MapInfo.Map.SelectedMap.CurrentTileSet == null) return;

            var clipRectangle = new XnaRectangle(e.ClipRectangle.X,e.ClipRectangle.Y,e.ClipRectangle.Width,e.ClipRectangle.Height);
            var destinationRect = new XnaRectangle();
            destinationRect.X = (int)Math.Floor(clipRectangle.X / (float)MapInfo.Map.SelectedMap.TileSize);
            destinationRect.Y = (int)Math.Floor(clipRectangle.Y / (float)MapInfo.Map.SelectedMap.TileSize);
            destinationRect.Width = (int)Math.Ceiling(clipRectangle.Width / (float)MapInfo.Map.SelectedMap.TileSize);
            destinationRect.Height = (int)Math.Ceiling(clipRectangle.Height / (float)MapInfo.Map.SelectedMap.TileSize);

            xnaGraphics.Begin();
            xnaGraphics.FillRectangle(clipRectangle, XnaColor.FromNonPremultiplied(BackColor.R, BackColor.G, BackColor.B, BackColor.A));
            xnaGraphics.Draw(MapInfo.Map.SelectedMap.CurrentTileSet.TilesImage, clipRectangle, clipRectangle, XnaColor.White);
            
            
            DrawGrid(destinationRect.Location, new XnaPoint(destinationRect.Right, destinationRect.Bottom));

            
            if (DataPainter != null)
                DataPainter.OnDraw(xnaGraphics, destinationRect);
            else
                MapInfo.Map.SelectedMap.CurrentTileSet.Selection.OnDraw(xnaGraphics, destinationRect);

            xnaGraphics.End();
        }


        void TileSet_SelectedDataGridChanged(MapInfo.Map map)
        {
            if (map.CurrentTileSet.CurrentDataGrid == null)
                DataPainter = null;
            else
                DataPainter = new DataPainter(map.CurrentTileSet.CurrentDataGrid,Services);
            Invalidate();
        }

        private void TileSet_PrimaryTileSetChanged(MapInfo.Map map)
        {
            DataPainter = null;
            if (map == null || map.CurrentTileSet == null)
            {
                Size = Size.Empty;
                if (backBuffer != null)
                {
                    backBuffer.Dispose();
                    backBuffer = null;
                }
            }
            else
            {
                var tileSet = map.CurrentTileSet;
                Size = new Size(tileSet.TilesImage.Width, tileSet.TilesImage.Height);
                if (backBuffer != null)
                {
                    backBuffer.Dispose();
                    backBuffer = null;
                }
                backBuffer = new RenderTarget2D(GraphicsDevice, Size.Width, Size.Height, false,
                                                SurfaceFormat.Color, DepthFormat.Depth24, 0,
                                                RenderTargetUsage.PreserveContents);
            }
        }


        private void DrawGrid(XnaPoint topLeft, XnaPoint buttomRight)
        {
            if (IsDrawGrid)
            {
                for (int i = topLeft.X; i < buttomRight.X && i < MapInfo.Map.SelectedMap.CurrentTileSet.TilesSize.X; i++)
                {
                    for (int j = topLeft.Y; j < buttomRight.Y && j < MapInfo.Map.SelectedMap.CurrentTileSet.TilesSize.Y; j++)
                    {
                        xnaGraphics.DrawRectangle(new XnaRectangle(i * MapInfo.Map.SelectedMap.TileSize, j * MapInfo.Map.SelectedMap.TileSize,
                                                             MapInfo.Map.SelectedMap.TileSize, MapInfo.Map.SelectedMap.TileSize), XnaColor.Multiply(XnaColor.White, .4f));
                    }
                }
            }
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left) return;

            var position = e.Location;
            position.X = MathEx.Clamp(position.X, 0, Width - 1);
            position.Y = MathEx.Clamp(position.Y, 0, Height - 1);

            var tilePosition = new XnaPoint(position.X / MapInfo.Map.SelectedMap.TileSize, position.Y / MapInfo.Map.SelectedMap.TileSize);

            XnaRectangle invalidationRectangle;

            if (DataPainter != null)
                invalidationRectangle = DataPainter.OnMouseDown(tilePosition, e.Button);
            else
                invalidationRectangle = MapInfo.Map.SelectedMap.CurrentTileSet.Selection.OnMouseDown(tilePosition, e.Button);

            if (invalidationRectangle != new XnaRectangle())
                Invalidate(MathEx.ConvertToSystemRect(MapInfo.Map.SelectedMap.CurrentTileSet.GetScreenSize(invalidationRectangle)));
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left) return;

            var position = e.Location;
            position.X = MathEx.Clamp(position.X, 0, Width - 1);
            position.Y = MathEx.Clamp(position.Y, 0, Height - 1);

            var tilePosition = new XnaPoint(position.X / MapInfo.Map.SelectedMap.TileSize, position.Y / MapInfo.Map.SelectedMap.TileSize);

            XnaRectangle invalidationRectangle;
                
            if (DataPainter != null)
                invalidationRectangle = DataPainter.OnMouseMove(tilePosition, e.Button);
            else
                invalidationRectangle = MapInfo.Map.SelectedMap.CurrentTileSet.Selection.OnMouseMove(tilePosition, e.Button);

            if (invalidationRectangle != new XnaRectangle())
                Invalidate(MathEx.ConvertToSystemRect(MapInfo.Map.SelectedMap.CurrentTileSet.GetScreenSize(invalidationRectangle)));
        }

        protected override void OnMouseEnter(EventArgs e)
        {
            Parent.Focus();

            base.OnMouseEnter(e);
        }
    }
}